package util.estatisticas.metricas;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;

import util.Util;
import util.graficos.GraficoPMF;

public class NumeroMedioUsuarios {
	
	private double t0;
	
	private int n0;
	
	private int rodada;
	
	private double instanteInicioRodada;
	
	private HashMap<Integer, Double> mapaNumeroUsuariosxTempoSistema;

	private GraficoPMF graficoPMF;
	
	/**
	 * Construtor
	 * 
	 */
	public NumeroMedioUsuarios() {
		this.t0 = 0;
		this.n0 = 0;
		this.mapaNumeroUsuariosxTempoSistema = new HashMap<Integer, Double>();
		
		if (Util.PLOTAR_GRAFICOS) {
			graficoPMF = new GraficoPMF();
		}
	}

	/**
	 * Chamado sempre que um novo usuário chega ao sistema, esse método computa o tempo em que o
	 * sistema permanece com uma certa quantidade de usuários (peers e seeds)
	 * 
	 * @param Instante de chegada de um novo usuário
	 */
	public void chegadaUsuario(final double t1) {
		this.mapaNumeroUsuariosxTempoSistema.put(this.n0, tempoGastoComN0Usuarios(t1));
		
		this.n0++;
		this.t0 = t1;
	}
	
	/**
	 * Chamado sempre que um usuário sai do sistema, esse método computa o tempo em que o
	 * sistema permanece com uma certa quantidade de usuários (peers e seeds)
	 * 
	 * @param Instante de saída de um usuário
	 */
	public void saidaUsuario(final double t1) {
		this.mapaNumeroUsuariosxTempoSistema.put(this.n0, tempoGastoComN0Usuarios(t1));
		
		this.n0--;
		this.t0 = t1;
	}

	/**
	 * 
	 * @param Instante de modificação no múmero de usuários
	 * @return Tempo do sistema com n0 usuários 
	 */
	private double tempoGastoComN0Usuarios(final double t1) {
		double tempoGastoComN0Usuarios = t1 - this.t0;
		if (this.mapaNumeroUsuariosxTempoSistema.containsKey(this.n0)) {
			tempoGastoComN0Usuarios += this.mapaNumeroUsuariosxTempoSistema.get(this.n0);
		}
		
		return tempoGastoComN0Usuarios;
	}

	/**
	 * Calcula o número de usuários na rodada.
	 * 
	 * @param rodada
	 * @param instanteInicioRodada 
	 * @param numeroUsuariosIniciaisRodada 
	 * @param listaPeer 
	 * @param listaSeed 
	 */
	public void calculaXi() {
		ArrayList<Integer> numeroUsuarios = new ArrayList<Integer>();
		numeroUsuarios.addAll(this.mapaNumeroUsuariosxTempoSistema.keySet());
		Collections.sort(numeroUsuarios);
		
		double tempo, x;
		double duracaoRodada = this.t0 - this.instanteInicioRodada;
		
		for (Integer n : numeroUsuarios) {
			tempo = this.mapaNumeroUsuariosxTempoSistema.get(n);
			x = tempo / duracaoRodada;
			
			if (Util.PLOTAR_GRAFICOS) {
				this.graficoPMF.adicionaPonto(n, x);
			}
		}
		
		if (Util.PLOTAR_GRAFICOS) {
			this.graficoPMF.plotaRodada(rodada);
		}
		
		this.mapaNumeroUsuariosxTempoSistema.clear();
	}

	/**
	 * Plota a PMF do número de usuários no sistema
	 */
	public void plotPMF() {
		if (Util.PLOTAR_GRAFICOS) {
			this.graficoPMF.plot();
		}
	}

	public void setNumeroUsuariosIniciaisRodada(int numeroUsuariosIniciaisRodada) {
		this.n0 = numeroUsuariosIniciaisRodada;
	}

	public void setRodada(int rodada) {
		this.rodada = rodada;
	}

	public void setInstanteInicioRodada(double instanteInicioRodada) {
		this.t0 = instanteInicioRodada;
		this.instanteInicioRodada = instanteInicioRodada;
	}
}
